Despesas por função (aqui!)
#library(extrafont)
#font_import()
#loadfonts()
tres_cores <-c("#F8AC08","#028063","#1E466A")
tres_cores_pasteis <- c("#FECE60","#63BEAF", "#7A9CBD")
tema_BSPN <- function(){
theme_minimal() +
theme(
text = element_text(family = "Source Sans Pro", colour = "grey20"),
axis.text = element_text(family = "Source Sans Pro", colour = "grey20"),
title = element_text(face = "bold"),
plot.subtitle = element_text(face = "plain"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.text = element_text(size = 8),
legend.title = element_text(size = 8),
legend.position = 'bottom')
}
desp_fun <- read_excel("funcao_2017.xlsx")
tabela_nomes_funcoes <- desp_fun[1:28,1:2]
desp_fun$pctU2017 <- 100*desp_fun$`UNIÃO_2017` / rowSums(desp_fun[,c(3,5,7)])
desp_fun$pctU2016 <- 100*desp_fun$`UNIÃO_2016` / rowSums(desp_fun[,c(4,6,8)])
desp_fun <- desp_fun[,c(1,2,9,10,3:8)]
d_fun <- desp_fun[c(1:28,31),] %>%
gather(-1:-4, key="Ente_Ano", value="valor") %>%
separate(Ente_Ano, into = c("Ente", "Ano")) # por padrão ele separa por qq caractere não-alfanumérico,
# ou se usaria um {,sep = "_"}
# uma tabelinha com totais e uma versão do dataframe com esses totais para ordenar o gráfico de vlrs absolutos
tot_fun_2017 <- d_fun %>%
group_by(Funcao, Ano) %>%
summarise(soma_funcao = sum(valor))
d_fun_tot <- d_fun %>%
left_join(tot_fun_2017)
Joining, by = c("Funcao", "Ano")
# uma outra tabelinha para comparar previdencia e encargos especiais com as demais funcoes
d_fun_demais <- d_fun %>%
filter(Ano=="2017" & !is.na(Funcao) & !(Funcao %in% c("28 - Encargos Especiais", "09 - Previdência Social"))) %>%
group_by(Ente,Ano) %>%
summarise(valor = sum(valor)) %>%
mutate(Funcao = "Demais funções")
d_fun_prevEnc <- d_fun %>%
filter(Ano=="2017" & !is.na(Funcao) & (Funcao %in% c("28 - Encargos Especiais", "09 - Previdência Social"))) %>%
select(Ente, Ano, valor, Funcao)
d_fun_principais <- d_fun_prevEnc %>%
bind_rows(d_fun_demais) %>%
mutate (Funcao = factor(Funcao))
# os gráficos
plot_fun_dark <- ggplot(d_fun %>% filter(Ano=="2017" & !is.na(Funcao)), aes(fill=Ente, y=valor, x=Funcao)) +
coord_flip() +
geom_bar( stat="identity", position="fill", width=0.6, color = "grey20", size = 1) +
labs(
x = NULL,
y = NULL,
fill = "Ente",
title = "Distribuição das despesas por ente da Federação",
subtitle = "Conforme a classificação funcional"
) +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(values = c("#8D993D","#406AFF","#FFD500")) +
theme_minimal() +
theme(
plot.background = element_rect(fill = "grey20"),
text = element_text(family = "Source Sans Pro", colour = "white"),
axis.text = element_text(family = "Source Sans Pro", colour = "white"),
title = element_text(face = "bold"),
plot.subtitle = element_text(face = "plain"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.text = element_text(size = 8),
legend.title = element_text(size = 8),
legend.position = 'bottom')
# fct_reorder muito útil! só que tenho q colocar em ordem descendente de PERCENTUAL, e não de valor. preciso
# criar essa variável.
plot_fun <- ggplot(
d_fun %>% filter(Ano=="2017" & !is.na(Funcao)),
aes(
fill = factor(Ente, levels = rev(c("UNIÃO", "ESTADOS", "MUNICÍPIOS"))),
y = valor,
x = fct_reorder(Funcao,pctU2017,desc=TRUE))) +
coord_flip() +
geom_bar( stat="identity", position="fill", width=0.6, color = "white", size = 1) +
labs(
x = NULL,
y = NULL,
fill = "Ente",
title = paste("Distribuição das despesas por ente da Federação ","\u2013"," 2017"),
subtitle = "Conforme a Classificação Funcional. Por ordem decrescente da participação da União no total da despesa."
) +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(values = tres_cores) +
tema_BSPN()
#reais <- scales::dollar_format(prefix = "R$ ", suffix = " bilhões", largest_with_cents = 1000, big.mark=".", decimal.mark=",")
#reais(10000)
plot_fun_abs <- ggplot(
d_fun_tot %>% filter(Ano=="2017" & !is.na(Funcao) & !(Funcao %in% c("28 - Encargos Especiais", "09 - Previdência Social"))),
aes(
fill = factor(Ente, levels = rev(c("UNIÃO", "ESTADOS", "MUNICÍPIOS"))),
y = valor/1000,
x = fct_reorder(Funcao,soma_funcao,desc=TRUE))) +
coord_flip() +
geom_bar( stat="identity", width=0.6, color = "white", size = 1) +
labs(
x = NULL,
y = NULL,
fill = "Ente",
title = paste("Despesas totais por Função ","\u2013"," 2017"),
subtitle = "Em bilhões de reais. Exceto funções \"28 - Encargos Especiais\" e \"09 - Previdência Social\"."
) +
#scale_y_discrete(breaks = c(0,100,200,300), labels = c("0","100","200","300")) +
#scale_y_continuous(limits = c(0,max(subset(d_fun_tot, d_fun_tot$Ano == "2017")$soma_funcao)/1000)) +
scale_y_continuous() + #uexpand = c(0,0) para zerar o padding entre o exito e o início do gráfico
scale_fill_manual(values = tres_cores) +
tema_BSPN()
formata_BR <- scales::format_format(big.mark = ".", decimal.mark = ",", scientific = FALSE)
plot_fun_abs_principais <- ggplot(
d_fun_principais,
aes(
fill = factor(Ente, levels = rev(c("UNIÃO", "ESTADOS", "MUNICÍPIOS"))),
y = valor/1000,
x = fct_rev(Funcao))) +
coord_flip() +
geom_bar( stat="identity", width=0.6, color = "white", size = 1) +
labs(
x = NULL,
y = NULL,
fill = "Ente",
title = paste("Despesas totais por Função ","\u2013"," 2017"),
subtitle = "Em bilhões de reais."
) +
#scale_y_discrete(breaks = c(0,100,200,300), labels = c("0","100","200","300")) +
#scale_y_continuous(limits = c(0,max(subset(d_fun_tot, d_fun_tot$Ano == "2017")$soma_funcao)/1000)) +
scale_y_continuous(labels = formata_BR) + #uexpand = c(0,0) para zerar o padding entre o exito e o início do gráfico
scale_fill_manual(values = tres_cores) +
tema_BSPN()
plot_fun

plot_fun_abs_principais

plot_fun_abs

pibs <- c(pibs, 6559940)
for (i in 1:length(pibs)){
sh_fun[,i+4] <- round(sh_fun[,i+4] / pibs[i], 4)
}
# passando para um formato tidy
sh_fun <- sh_fun %>%
gather(5:20, key="Ano", value="Valor")
# funcoes para plotar os gráficos de barra
plot_funcoes <- function(funcao){
ggplot(
sh_fun %>% filter(Funcao_Maius==funcao & ente != "Consolidado"),
aes(
fill = factor(ente, levels = rev(c("União", "Estados", "Municípios"))),
y = Valor,
x = Ano)) +
#coord_flip() +
geom_bar(stat = "identity", width=0.7, color = "white", size = 1) + #position = "fill"
#geom_area(aes(group = ente),stat = "identity", position = "stack", color = "white") + #position = "fill"
labs(
x = NULL,
y = NULL,
fill = "Ente",
title = paste("Distribuição das despesas com ", tolower(funcao), " por ente da Federação ","2002\u2013","2017", sep=""),
subtitle = "Em percentuais do PIB."
) +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(values = tres_cores) +
geom_text(aes(label= scales::percent(Valor)),size = 3, position = position_stack(vjust = 0.5), hjust = 0.5, family = "Source Sans Pro", color = "white") +
tema_BSPN()
}
funcoes_de_interesse <- c("EDUCAÇÃO", "SAÚDE", "ASSISTÊNCIA SOCIAL", "SEGURANÇA PÚBLICA")
lapply(funcoes_de_interesse, plot_funcoes)
[[1]]
[[2]]
[[3]]
[[4]]




# plot_funcoes("EDUCAÇÃO")
# plot_funcoes("SAÚDE")
# plot_funcoes("ASSISTÊNCIA SOCIAL")
# plot_funcoes("SEGURANÇA PÚBLICA")
#ggplot(serie_f %>% filter(Funcao=="EDUCAÇÃO"), aes(x = Ano, y = Valor)) +
#geom_point(aes(color=ente))+
#geom_line(aes(group=ente))
#geom_area(aes(fill = ente, group = ente), stat = "identity", position="stack")
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdGhlbWU6IGNvc21vDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KICAgIGRmX3ByaW50OiBwYWdlZA0KLS0tDQoNCmBgYHtjc3N9DQouZHlncmFwaC1sZWdlbmQsIC5keWdyYXBoLWF4aXMtbGFiZWwgew0KICBmb250LWZhbWlseTogIlNvdXJjZSBTYW5zIFBybyI7DQp9DQoNCi5keWdyYXBoLWxhYmVsIHsNCiAgZm9udC1mYW1pbHk6ICJTb3VyY2UgU2FucyBQcm8iOw0KfQ0KYGBgDQoNCg0KYGBge3J9DQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQojIyBEZXNwZXNhcyBwb3IgZnVuw6fDo28gKGFxdWkhKQ0KDQpgYGB7ciBmdW5jYW99DQojbGlicmFyeShleHRyYWZvbnQpDQojZm9udF9pbXBvcnQoKQ0KI2xvYWRmb250cygpDQoNCnRyZXNfY29yZXMgPC1jKCIjRjhBQzA4IiwiIzAyODA2MyIsIiMxRTQ2NkEiKQ0KdHJlc19jb3Jlc19wYXN0ZWlzIDwtIGMoIiNGRUNFNjAiLCIjNjNCRUFGIiwgIiM3QTlDQkQiKQ0KDQp0ZW1hX0JTUE4gPC0gZnVuY3Rpb24oKXsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHRoZW1lKA0KICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiU291cmNlIFNhbnMgUHJvIiwgY29sb3VyID0gImdyZXkyMCIpLA0KICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJTb3VyY2UgU2FucyBQcm8iLCBjb2xvdXIgPSAiZ3JleTIwIiksDQogICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwNCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIpLA0KICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgDQogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nKQ0KfQ0KDQpkZXNwX2Z1biA8LSByZWFkX2V4Y2VsKCJmdW5jYW9fMjAxNy54bHN4IikNCg0KdGFiZWxhX25vbWVzX2Z1bmNvZXMgPC0gZGVzcF9mdW5bMToyOCwxOjJdDQoNCmRlc3BfZnVuJHBjdFUyMDE3IDwtIDEwMCpkZXNwX2Z1biRgVU5Jw4NPXzIwMTdgIC8gcm93U3VtcyhkZXNwX2Z1blssYygzLDUsNyldKQ0KZGVzcF9mdW4kcGN0VTIwMTYgPC0gMTAwKmRlc3BfZnVuJGBVTknDg09fMjAxNmAgLyByb3dTdW1zKGRlc3BfZnVuWyxjKDQsNiw4KV0pDQoNCmRlc3BfZnVuIDwtIGRlc3BfZnVuWyxjKDEsMiw5LDEwLDM6OCldDQoNCmRfZnVuIDwtIGRlc3BfZnVuW2MoMToyOCwzMSksXSAlPiUNCiAgZ2F0aGVyKC0xOi00LCBrZXk9IkVudGVfQW5vIiwgdmFsdWU9InZhbG9yIikgJT4lDQogIHNlcGFyYXRlKEVudGVfQW5vLCBpbnRvID0gYygiRW50ZSIsICJBbm8iKSkgIyBwb3IgcGFkcsOjbyBlbGUgc2VwYXJhIHBvciBxcSBjYXJhY3RlcmUgbsOjby1hbGZhbnVtw6lyaWNvLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG91IHNlIHVzYXJpYSB1bSB7LHNlcCA9ICJfIn0NCg0KIyB1bWEgdGFiZWxpbmhhIGNvbSB0b3RhaXMgZSB1bWEgdmVyc8OjbyBkbyBkYXRhZnJhbWUgY29tIGVzc2VzIHRvdGFpcyBwYXJhIG9yZGVuYXIgbyBncsOhZmljbyBkZSB2bHJzIGFic29sdXRvcw0KDQp0b3RfZnVuXzIwMTcgPC0gZF9mdW4gJT4lDQogIGdyb3VwX2J5KEZ1bmNhbywgQW5vKSAlPiUNCiAgc3VtbWFyaXNlKHNvbWFfZnVuY2FvID0gc3VtKHZhbG9yKSkNCg0KZF9mdW5fdG90IDwtIGRfZnVuICU+JQ0KICBsZWZ0X2pvaW4odG90X2Z1bl8yMDE3KQ0KDQojIHVtYSBvdXRyYSB0YWJlbGluaGEgcGFyYSBjb21wYXJhciBwcmV2aWRlbmNpYSBlIGVuY2FyZ29zIGVzcGVjaWFpcyBjb20gYXMgZGVtYWlzIGZ1bmNvZXMNCg0KZF9mdW5fZGVtYWlzIDwtIGRfZnVuICU+JQ0KICBmaWx0ZXIoQW5vPT0iMjAxNyIgJiAhaXMubmEoRnVuY2FvKSAmICEoRnVuY2FvICVpbiUgYygiMjggLSBFbmNhcmdvcyBFc3BlY2lhaXMiLCAiMDkgLSBQcmV2aWTDqm5jaWEgU29jaWFsIikpKSAlPiUNCiAgZ3JvdXBfYnkoRW50ZSxBbm8pICU+JQ0KICBzdW1tYXJpc2UodmFsb3IgPSBzdW0odmFsb3IpKSAlPiUNCiAgbXV0YXRlKEZ1bmNhbyA9ICJEZW1haXMgZnVuw6fDtWVzIikNCg0KZF9mdW5fcHJldkVuYyA8LSBkX2Z1biAlPiUgDQogIGZpbHRlcihBbm89PSIyMDE3IiAmICFpcy5uYShGdW5jYW8pICYgKEZ1bmNhbyAlaW4lIGMoIjI4IC0gRW5jYXJnb3MgRXNwZWNpYWlzIiwgIjA5IC0gUHJldmlkw6puY2lhIFNvY2lhbCIpKSkgJT4lDQogIHNlbGVjdChFbnRlLCBBbm8sIHZhbG9yLCBGdW5jYW8pDQoNCmRfZnVuX3ByaW5jaXBhaXMgPC0gZF9mdW5fcHJldkVuYyAlPiUNCiAgYmluZF9yb3dzKGRfZnVuX2RlbWFpcykgJT4lDQogIG11dGF0ZSAoRnVuY2FvID0gZmFjdG9yKEZ1bmNhbykpDQoNCiMgb3MgZ3LDoWZpY29zDQoNCnBsb3RfZnVuX2RhcmsgPC0gZ2dwbG90KGRfZnVuICU+JSBmaWx0ZXIoQW5vPT0iMjAxNyIgJiAhaXMubmEoRnVuY2FvKSksIGFlcyhmaWxsPUVudGUsIHk9dmFsb3IsIHg9RnVuY2FvKSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2VvbV9iYXIoIHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb249ImZpbGwiLCB3aWR0aD0wLjYsIGNvbG9yID0gImdyZXkyMCIsIHNpemUgPSAxKSArDQogICAgbGFicygNCiAgICAgIHggPSBOVUxMLA0KICAgICAgeSA9IE5VTEwsDQogICAgICBmaWxsID0gIkVudGUiLA0KICAgICAgdGl0bGUgPSAiRGlzdHJpYnVpw6fDo28gZGFzIGRlc3Blc2FzIHBvciBlbnRlIGRhIEZlZGVyYcOnw6NvIiwNCiAgICAgIHN1YnRpdGxlID0gIkNvbmZvcm1lIGEgY2xhc3NpZmljYcOnw6NvIGZ1bmNpb25hbCINCiAgICApICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzhEOTkzRCIsIiM0MDZBRkYiLCIjRkZENTAwIikpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JleTIwIiksDQogICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJTb3VyY2UgU2FucyBQcm8iLCBjb2xvdXIgPSAid2hpdGUiKSwNCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiU291cmNlIFNhbnMgUHJvIiwgY29sb3VyID0gIndoaXRlIiksDQogICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwNCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIpLA0KICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgDQogICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nKQ0KDQojIGZjdF9yZW9yZGVyIG11aXRvIMO6dGlsISBzw7MgcXVlIHRlbmhvIHEgY29sb2NhciBlbSBvcmRlbSBkZXNjZW5kZW50ZSBkZSBQRVJDRU5UVUFMLCBlIG7Do28gZGUgdmFsb3IuIHByZWNpc28NCiMgY3JpYXIgZXNzYSB2YXJpw6F2ZWwuDQoNCnBsb3RfZnVuIDwtIGdncGxvdCgNCiAgICAgIGRfZnVuICU+JSBmaWx0ZXIoQW5vPT0iMjAxNyIgJiAhaXMubmEoRnVuY2FvKSksIA0KICAgICAgYWVzKA0KICAgICAgICBmaWxsID0gZmFjdG9yKEVudGUsIGxldmVscyA9IHJldihjKCJVTknDg08iLCAiRVNUQURPUyIsICJNVU5JQ8ONUElPUyIpKSksIA0KICAgICAgICB5ID0gdmFsb3IsIA0KICAgICAgICB4ID0gZmN0X3Jlb3JkZXIoRnVuY2FvLHBjdFUyMDE3LGRlc2M9VFJVRSkpKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZW9tX2Jhciggc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbj0iZmlsbCIsIHdpZHRoPTAuNiwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMSkgKw0KICAgIGxhYnMoDQogICAgICB4ID0gTlVMTCwNCiAgICAgIHkgPSBOVUxMLA0KICAgICAgZmlsbCA9ICJFbnRlIiwNCiAgICAgIHRpdGxlID0gcGFzdGUoIkRpc3RyaWJ1acOnw6NvIGRhcyBkZXNwZXNhcyBwb3IgZW50ZSBkYSBGZWRlcmHDp8OjbyAiLCJcdTIwMTMiLCIgMjAxNyIpLA0KICAgICAgc3VidGl0bGUgPSAiQ29uZm9ybWUgYSBDbGFzc2lmaWNhw6fDo28gRnVuY2lvbmFsLiBQb3Igb3JkZW0gZGVjcmVzY2VudGUgZGEgcGFydGljaXBhw6fDo28gZGEgVW5pw6NvIG5vIHRvdGFsIGRhIGRlc3Blc2EuIg0KICAgICkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsNCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB0cmVzX2NvcmVzKSArDQogICAgdGVtYV9CU1BOKCkNCg0KI3JlYWlzIDwtIHNjYWxlczo6ZG9sbGFyX2Zvcm1hdChwcmVmaXggPSAiUiQgIiwgc3VmZml4ID0gIiBiaWxow7VlcyIsIGxhcmdlc3Rfd2l0aF9jZW50cyA9IDEwMDAsIGJpZy5tYXJrPSIuIiwgZGVjaW1hbC5tYXJrPSIsIikNCiNyZWFpcygxMDAwMCkNCg0KcGxvdF9mdW5fYWJzIDwtIGdncGxvdCgNCiAgICAgIGRfZnVuX3RvdCAlPiUgZmlsdGVyKEFubz09IjIwMTciICYgIWlzLm5hKEZ1bmNhbykgJiAhKEZ1bmNhbyAlaW4lIGMoIjI4IC0gRW5jYXJnb3MgRXNwZWNpYWlzIiwgIjA5IC0gUHJldmlkw6puY2lhIFNvY2lhbCIpKSksIA0KICAgICAgYWVzKA0KICAgICAgICBmaWxsID0gZmFjdG9yKEVudGUsIGxldmVscyA9IHJldihjKCJVTknDg08iLCAiRVNUQURPUyIsICJNVU5JQ8ONUElPUyIpKSksIA0KICAgICAgICB5ID0gdmFsb3IvMTAwMCwgDQogICAgICAgIHggPSBmY3RfcmVvcmRlcihGdW5jYW8sc29tYV9mdW5jYW8sZGVzYz1UUlVFKSkpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGdlb21fYmFyKCBzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTAuNiwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMSkgKw0KICAgIGxhYnMoDQogICAgICB4ID0gTlVMTCwNCiAgICAgIHkgPSBOVUxMLA0KICAgICAgZmlsbCA9ICJFbnRlIiwNCiAgICAgIHRpdGxlID0gcGFzdGUoIkRlc3Blc2FzIHRvdGFpcyBwb3IgRnVuw6fDo28gIiwiXHUyMDEzIiwiIDIwMTciKSwNCiAgICAgIHN1YnRpdGxlID0gIkVtIGJpbGjDtWVzIGRlIHJlYWlzLiBFeGNldG8gZnVuw6fDtWVzIFwiMjggLSBFbmNhcmdvcyBFc3BlY2lhaXNcIiBlIFwiMDkgLSBQcmV2aWTDqm5jaWEgU29jaWFsXCIuIg0KICAgICkgKw0KICAgICNzY2FsZV95X2Rpc2NyZXRlKGJyZWFrcyA9IGMoMCwxMDAsMjAwLDMwMCksIGxhYmVscyA9IGMoIjAiLCIxMDAiLCIyMDAiLCIzMDAiKSkgKw0KICAgICNzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLG1heChzdWJzZXQoZF9mdW5fdG90LCBkX2Z1bl90b3QkQW5vID09ICIyMDE3Iikkc29tYV9mdW5jYW8pLzEwMDApKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKCkgKyAjdWV4cGFuZCA9IGMoMCwwKSBwYXJhIHplcmFyIG8gcGFkZGluZyBlbnRyZSBvIGV4aXRvIGUgbyBpbsOtY2lvIGRvIGdyw6FmaWNvIA0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHRyZXNfY29yZXMpICsNCiAgICB0ZW1hX0JTUE4oKQ0KDQpmb3JtYXRhX0JSIDwtIHNjYWxlczo6Zm9ybWF0X2Zvcm1hdChiaWcubWFyayA9ICIuIiwgZGVjaW1hbC5tYXJrID0gIiwiLCBzY2llbnRpZmljID0gRkFMU0UpDQoNCnBsb3RfZnVuX2Fic19wcmluY2lwYWlzIDwtIGdncGxvdCgNCiAgICAgIGRfZnVuX3ByaW5jaXBhaXMsIA0KICAgICAgYWVzKA0KICAgICAgICBmaWxsID0gZmFjdG9yKEVudGUsIGxldmVscyA9IHJldihjKCJVTknDg08iLCAiRVNUQURPUyIsICJNVU5JQ8ONUElPUyIpKSksIA0KICAgICAgICB5ID0gdmFsb3IvMTAwMCwgDQogICAgICAgIHggPSBmY3RfcmV2KEZ1bmNhbykpKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZW9tX2Jhciggc3RhdD0iaWRlbnRpdHkiLCB3aWR0aD0wLjYsIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDEpICsNCiAgICBsYWJzKA0KICAgICAgeCA9IE5VTEwsDQogICAgICB5ID0gTlVMTCwNCiAgICAgIGZpbGwgPSAiRW50ZSIsDQogICAgICB0aXRsZSA9IHBhc3RlKCJEZXNwZXNhcyB0b3RhaXMgcG9yIEZ1bsOnw6NvICIsIlx1MjAxMyIsIiAyMDE3IiksDQogICAgICBzdWJ0aXRsZSA9ICJFbSBiaWxow7VlcyBkZSByZWFpcy4iDQogICAgKSArDQogICAgI3NjYWxlX3lfZGlzY3JldGUoYnJlYWtzID0gYygwLDEwMCwyMDAsMzAwKSwgbGFiZWxzID0gYygiMCIsIjEwMCIsIjIwMCIsIjMwMCIpKSArDQogICAgI3NjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsbWF4KHN1YnNldChkX2Z1bl90b3QsIGRfZnVuX3RvdCRBbm8gPT0gIjIwMTciKSRzb21hX2Z1bmNhbykvMTAwMCkpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZm9ybWF0YV9CUikgKyAjdWV4cGFuZCA9IGMoMCwwKSBwYXJhIHplcmFyIG8gcGFkZGluZyBlbnRyZSBvIGV4aXRvIGUgbyBpbsOtY2lvIGRvIGdyw6FmaWNvIA0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHRyZXNfY29yZXMpICsNCiAgICB0ZW1hX0JTUE4oKQ0KDQpwbG90X2Z1bg0KcGxvdF9mdW5fYWJzX3ByaW5jaXBhaXMNCnBsb3RfZnVuX2Ficw0KDQoNCg0KDQpgYGANCg0KYGBge3Igc2VyaWUtaGlzdG9yaWNhLWZ1bmNhb30NCg0KZnVuX211biA8LSByZWFkX2V4Y2VsKCJjb25zb2xfc2VyaWUueGxzIiwgc2hlZXQ9IkZ1bmNhbyBNdW5pY2lwaW9zIixza2lwPTExLHRyaW1fd3M9RkFMU0UpDQpmdW5fZXN0IDwtIHJlYWRfZXhjZWwoImNvbnNvbF9zZXJpZS54bHMiLCBzaGVldD0iRnVuY2FvIEVzdGFkb3MiLHNraXA9MTEsdHJpbV93cz1GQUxTRSkNCmZ1bl91bmkgPC0gcmVhZF9leGNlbCgiY29uc29sX3NlcmllLnhscyIsIHNoZWV0PSJGdW5jYW8gVW5pYW8iLHNraXA9MTEsdHJpbV93cz1GQUxTRSkNCmZ1bl9jb24gPC0gcmVhZF9leGNlbCgiY29uc29sX3NlcmllLnhscyIsIHNoZWV0PSJGdW5jYW8gQ29uc29saWRhZG8iLHNraXA9MTEsdHJpbV93cz1GQUxTRSkNCg0KZnVuX211bjIgPC0gcmVhZF9leGNlbCgiY29tcGxlbWVudG9fc2VyaWVfZnVuY29lc18yMDEzXzIwMTcueGxzeCIsIHNoZWV0PSJGdW7Dp8OjbyBNdW5pY8OtcGlvcyIsIHRyaW1fd3M9RkFMU0UpDQpmdW5fZXN0MiA8LSByZWFkX2V4Y2VsKCJjb21wbGVtZW50b19zZXJpZV9mdW5jb2VzXzIwMTNfMjAxNy54bHN4Iiwgc2hlZXQ9IkZ1bsOnw6NvIEVzdGFkb3MiLCB0cmltX3dzPUZBTFNFKQ0KZnVuX3VuaTIgPC0gcmVhZF9leGNlbCgiY29tcGxlbWVudG9fc2VyaWVfZnVuY29lc18yMDEzXzIwMTcueGxzeCIsIHNoZWV0PSJGdW7Dp8OjbyBVbmnDo28iLCB0cmltX3dzPUZBTFNFKQ0KZnVuX2NvbjIgPC0gcmVhZF9leGNlbCgiY29tcGxlbWVudG9fc2VyaWVfZnVuY29lc18yMDEzXzIwMTcueGxzeCIsIHNoZWV0PSJGdW7Dp8OjbyBDb25zb2xpZGFkbyIsIHRyaW1fd3M9RkFMU0UpDQoNCnRhYmVsYV9ub21lc19mdW5jb2VzJEZ1bmNhb19NYWl1cyA8LSB0b3VwcGVyKHRhYmVsYV9ub21lc19mdW5jb2VzJE5vbWVfZnVuY2FvKQ0KDQojIG8gdGVzdGUuLi4NCiMgDQojIHNoX2Z1bl9jb24gPC0gZnVuX2NvbiAlPiUNCiMgICBpbm5lcl9qb2luKHRhYmVsYV9ub21lc19mdW5jb2VzLCBieSA9IGMoIkZVTsOHw4NPL1NVQkZVTsOHw4NPIiA9ICJGdW5jYW9fTWFpdXMiKSkgJT4lDQojICAgcmVuYW1lKEZ1bmNhb19NYWl1cyA9IGBGVU7Dh8ODTy9TVUJGVU7Dh8ODT2ApICU+JQ0KIyAgIG11dGF0ZV9hdCgyOjE0LCBmdW5zKC4vMTAwMDAwMCkpICU+JSAjd293IQ0KIyAgIHNlbGVjdCgxNSwxNiwxLDI6MTQpICU+JQ0KIyAgIGxlZnRfam9pbihmdW5fY29uMiwgYnkgPSBjKCJGdW5jYW8iID0gIlhfXzEiKSkNCg0KIyB1bWEgZnVuw6fDo28gcGFyYSBwcm9jZXNzYXIgZXNzZXMgYXJxdWl2b3MgZSBqdW50w6EtbG9zLiBvbGhhIHF1ZSBjb2lzYSBsaW5kYS4NCg0KZ2VyYV9zaCA8LSBmdW5jdGlvbihzaDEsIHNoMil7DQogIHNoMSAlPiUNCiAgICBpbm5lcl9qb2luKHRhYmVsYV9ub21lc19mdW5jb2VzLCBieSA9IGMoIkZVTsOHw4NPL1NVQkZVTsOHw4NPIiA9ICJGdW5jYW9fTWFpdXMiKSkgJT4lDQogICAgcmVuYW1lKEZ1bmNhb19NYWl1cyA9IGBGVU7Dh8ODTy9TVUJGVU7Dh8ODT2ApICU+JQ0KICAgIG11dGF0ZV9hdCgyOjE0LCBmdW5zKC4vMTAwMDAwMCkpICU+JSAjd293ISBwcSBhcyBwcmltZWlyYXMgdGFiZWxhcyBlc3TDo28gZW0gUiQsIGFzIHNlZ3VuZGFzIGVtIG1pbGjDtWVzDQogICAgc2VsZWN0KDE1LDE2LDEsNDoxNCkgJT4lICMgZGVzcHJlemFuZG8gb3MgYW5vcyBkZSAyMDAwIGUgMjAwMSAoY29sdW5hcyAyIGUgMyksIHBvciBlc3RhcmVtIGluY29tcGxldG9zLg0KICAgIGxlZnRfam9pbihzaDIsIGJ5ID0gYygiRnVuY2FvIiA9ICJYX18xIikpICAgIA0KfQ0KDQpzaF9mdW5fY29uIDwtIGdlcmFfc2goZnVuX2NvbiwgZnVuX2NvbjIpDQpzaF9mdW5fbXVuIDwtIGdlcmFfc2goZnVuX211biwgZnVuX211bjIpDQpzaF9mdW5fZXN0IDwtIGdlcmFfc2goZnVuX2VzdCwgZnVuX2VzdDIpDQpzaF9mdW5fdW5pIDwtIGdlcmFfc2goZnVuX3VuaSwgZnVuX3VuaTIpDQoNCiMgYWNyZXNjZW50YXIgbyAiZW50ZSIgZW0gY2FkYSB0YWJlbGEgZSBqdW50YXIgdHVkbw0KDQpsaXN0YV9kZnMgPC0gbGlzdChzaF9mdW5fY29uLCBzaF9mdW5fbXVuLCBzaF9mdW5fZXN0LCBzaF9mdW5fdW5pKQ0KZW50ZXMgPC0gYygiQ29uc29saWRhZG8iLCAiTXVuaWPDrXBpb3MiLCAiRXN0YWRvcyIsICJVbmnDo28iKQ0KDQpmb3IgKGkgaW4gMTo0KXsNCiAgbGlzdGFfZGZzW1tpXV0kZW50ZSA8LSBlbnRlc1tpXQ0KfQ0KDQpzaF9mdW4gPC0gYmluZF9yb3dzKGxpc3RhX2RmcykNCnNoX2Z1biA8LSBzaF9mdW5bLGMoMTozLDIwLDQ6MTkpXQ0KDQojIGPDs2RpZ28gYW50aWdvDQojDQojIG11biA8LSBmdW5fbXVuW3doaWNoKGZ1bl9tdW4kYEZVTsOHw4NPL1NVQkZVTsOHw4NPYCAlaW4lIGZ1bmNvZXNfZGVfaW50ZXJlc3NlKSxdDQojIG11biRlbnRlIDwtICJNdW5pY8OtcGlvcyINCiMgDQojIGVzdCA8LSBmdW5fZXN0W3doaWNoKGZ1bl9lc3QkYEZVTsOHw4NPL1NVQkZVTsOHw4NPYCAlaW4lIGZ1bmNvZXNfZGVfaW50ZXJlc3NlKSxdDQojIGVzdCRlbnRlIDwtICJFc3RhZG9zIg0KIyANCiMgdW5pIDwtIGZ1bl91bmlbd2hpY2goZnVuX3VuaSRgRlVOw4fDg08vU1VCRlVOw4fDg09gICVpbiUgZnVuY29lc19kZV9pbnRlcmVzc2UpLF0NCiMgdW5pJGVudGUgPC0gIlVuacOjbyINCiMgDQojIHNlcmllX2Z1bmNvZXMgPC0gcmJpbmQobXVuLGVzdCx1bmkpWywtMjotM10NCg0KIyBub3JtYWxpemFyIHBlbG8gcGliIGFnb3JhDQoNCiMjIGltcG9ydGEgcGliIGRvIElwZWFEYXRhDQoNCmxpYnJhcnkoaXBlYURhdGEpDQpwaWJzIDwtIGlwZWFkYXRhKCJCTTEyX1BJQkFDMTIiKQ0KcGlicyA8LSBwaWJzW01FUz09IjEyIiAmIEFOTyAlaW4lICgyMDAyOjIwMTcpXSRWQUxWQUxPUg0KDQojIyBpbmNvcnBvcmEgbmEgbcOjbyBwaWIgZGUgMjAxNyBxdWUgYWluZGEgbsOjbyBlc3RhdmEgZGlzcG9uw612ZWwgbm8gcGFjb3RlIGlwZWFEYXRhLiBQZWd1ZWkgZG8gSUJHRS4NCg0KcGlicyA8LSBjKHBpYnMsIDY1NTk5NDApDQoNCmZvciAoaSBpbiAxOmxlbmd0aChwaWJzKSl7DQogIHNoX2Z1blssaSs0XSA8LSByb3VuZChzaF9mdW5bLGkrNF0gLyBwaWJzW2ldLCA0KQ0KfQ0KDQojIHBhc3NhbmRvIHBhcmEgdW0gZm9ybWF0byB0aWR5DQoNCnNoX2Z1biA8LSBzaF9mdW4gJT4lDQogIGdhdGhlcig1OjIwLCBrZXk9IkFubyIsIHZhbHVlPSJWYWxvciIpDQoNCg0KIyBmdW5jb2VzIHBhcmEgcGxvdGFyIG9zIGdyw6FmaWNvcyBkZSBiYXJyYQ0KDQpwbG90X2Z1bmNvZXMgPC0gZnVuY3Rpb24oZnVuY2FvKXsNCiAgZ2dwbG90KA0KICAgICAgc2hfZnVuICU+JSBmaWx0ZXIoRnVuY2FvX01haXVzPT1mdW5jYW8gJiBlbnRlICE9ICJDb25zb2xpZGFkbyIpLCANCiAgICAgIGFlcygNCiAgICAgICAgZmlsbCA9IGZhY3RvcihlbnRlLCBsZXZlbHMgPSByZXYoYygiVW5pw6NvIiwgIkVzdGFkb3MiLCAiTXVuaWPDrXBpb3MiKSkpLCANCiAgICAgICAgeSA9IFZhbG9yLCANCiAgICAgICAgeCA9IEFubykpICsNCiAgICAjY29vcmRfZmxpcCgpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGg9MC43LCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAxKSArICNwb3NpdGlvbiA9ICJmaWxsIg0KICAgICNnZW9tX2FyZWEoYWVzKGdyb3VwID0gZW50ZSksc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gInN0YWNrIiwgY29sb3IgPSAid2hpdGUiKSArICNwb3NpdGlvbiA9ICJmaWxsIg0KICAgIGxhYnMoDQogICAgICB4ID0gTlVMTCwNCiAgICAgIHkgPSBOVUxMLA0KICAgICAgZmlsbCA9ICJFbnRlIiwNCiAgICAgIHRpdGxlID0gcGFzdGUoIkRpc3RyaWJ1acOnw6NvIGRhcyBkZXNwZXNhcyBjb20gIiwgdG9sb3dlcihmdW5jYW8pLCAiIHBvciBlbnRlIGRhIEZlZGVyYcOnw6NvICIsIjIwMDJcdTIwMTMiLCIyMDE3Iiwgc2VwPSIiKSwNCiAgICAgIHN1YnRpdGxlID0gIkVtIHBlcmNlbnR1YWlzIGRvIFBJQi4iDQogICAgKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKw0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHRyZXNfY29yZXMpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsPSBzY2FsZXM6OnBlcmNlbnQoVmFsb3IpKSxzaXplID0gMywgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIGhqdXN0ID0gMC41LCBmYW1pbHkgPSAiU291cmNlIFNhbnMgUHJvIiwgY29sb3IgPSAid2hpdGUiKSArDQogICAgdGVtYV9CU1BOKCkNCn0NCg0KZnVuY29lc19kZV9pbnRlcmVzc2UgPC0gYygiRURVQ0HDh8ODTyIsICJTQcOaREUiLCAiQVNTSVNUw4pOQ0lBIFNPQ0lBTCIsICJTRUdVUkFOw4dBIFDDmkJMSUNBIikNCg0KbGFwcGx5KGZ1bmNvZXNfZGVfaW50ZXJlc3NlLCBwbG90X2Z1bmNvZXMpDQoNCiMgcGxvdF9mdW5jb2VzKCJFRFVDQcOHw4NPIikNCiMgcGxvdF9mdW5jb2VzKCJTQcOaREUiKQ0KIyBwbG90X2Z1bmNvZXMoIkFTU0lTVMOKTkNJQSBTT0NJQUwiKQ0KIyBwbG90X2Z1bmNvZXMoIlNFR1VSQU7Dh0EgUMOaQkxJQ0EiKQ0KDQojZ2dwbG90KHNlcmllX2YgJT4lIGZpbHRlcihGdW5jYW89PSJFRFVDQcOHw4NPIiksIGFlcyh4ID0gQW5vLCB5ID0gVmFsb3IpKSArDQogICNnZW9tX3BvaW50KGFlcyhjb2xvcj1lbnRlKSkrDQogICNnZW9tX2xpbmUoYWVzKGdyb3VwPWVudGUpKQ0KICAjZ2VvbV9hcmVhKGFlcyhmaWxsID0gZW50ZSwgZ3JvdXAgPSBlbnRlKSwgc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uPSJzdGFjayIpDQoNCmBgYA0KIyMgVG9kYXMgYXMgZnVuw6fDtWVzDQoNCmBgYHtyfQ0KdGFiZWxhX3NoIDwtIHNoX2Z1biAlPiUgDQogIGZpbHRlcihlbnRlID09ICJDb25zb2xpZGFkbyIpICU+JQ0KICBzZWxlY3QoMSw1LDYpICU+JQ0KICBzcHJlYWQoa2V5ID0gIkFubyIsIHZhbHVlID0gIlZhbG9yIikNCg0Kd3JpdGUuY3N2Mih0YWJlbGFfc2gsIGZpbGU9InRhYmVsYV9zaC5jc3YiKQ0KDQpzaF9saW5oYXMgPC0gc2hfZnVuICU+JSANCiAgZmlsdGVyKGVudGUgPT0gIkNvbnNvbGlkYWRvIiAmICEoRnVuY2FvICVpbiUgYygiMjggLSBFbmNhcmdvcyBFc3BlY2lhaXMiLCAiMDkgLSBQcmV2aWTDqm5jaWEgU29jaWFsIikpKSAlPiUNCiAgbXV0YXRlKFZhbG9yID0gVmFsb3IqMTAwKQ0KDQpsaWJyYXJ5KGhpZ2hjaGFydGVyKQ0KDQpoY2hhcnQoc2hfbGluaGFzLCAibGluZSIsIGhjYWVzKHggPSAiQW5vIiwgeSA9ICJWYWxvciIsIGdyb3VwID0gIkZ1bmNhbyIpLA0KICAgICAgIGxlZ2VuZCA9IGxpc3QoDQogICAgICAgICBzdHlsZSA9IGxpc3QoDQogICAgICAgICAgIGZvbnRXZWlnaHQgPSAncGxhaW4nKSkNCiAgICAgICAgICkNCg0KaGNoYXJ0KHNoX2xpbmhhcywgImxpbmUiLCBoY2Flcyh4ID0gIkFubyIsIHkgPSAiVmFsb3IiLCBncm91cCA9ICJGdW5jYW8iKSkgJT4lDQogIGhjX2xlZ2VuZChzdHlsZSA9IGxpc3QoZm9udFdlaWdodCA9ICJwbGFpbiIsIGNvbG9yID0gIiM0NTg5MzkiKSkgJT4lDQogIGhjX3lBeGlzKHRpdGxlID0gbGlzdCh0ZXh0ID0gIlZhbG9yIGVtIHBlcmNlbnR1YWwgZG8gUElCIikpICU+JQ0KICBoY190b29sdGlwKHNoYXJlZCA9ICJUUlVFIikNCg0KIyBjb20gZHlncmFwaHMNCg0KIyBjb252ZXJ0ZXIgYW5vIGVtIGRhdGEsIGUgbyBkYXRhZnJhbWUgZW0gdGltZSBzZXJpZXMNCg0KbGlicmFyeSh4dHMpDQpsaWJyYXJ5KGR5Z3JhcGhzKQ0KDQpzaF94dHMgPC0gc2hfbGluaGFzDQpzaF94dHMkQW5vIDwtIGFzLkRhdGUocGFzdGUoc2hfeHRzJEFubywgMTIsIDMxLCBzZXAgPSAiLSIpKQ0KDQpzaF94dHNbMjo0XSA8LSBOVUxMIA0Kc2hfeHRzJEZ1bmNhbyA8LSBhcy5mYWN0b3Ioc2hfeHRzJEZ1bmNhbykNCnNoX3h0cyA8LSBzaF94dHMgJT4lDQogIHNwcmVhZChrZXkgPSAiRnVuY2FvIiwgdmFsdWUgPSAiVmFsb3IiKQ0Kc2hfeHRzIDwtIHh0cyhzaF94dHNbLC0xXSwgb3JkZXIuYnkgPSBzaF94dHMkQW5vKQ0KDQojIGNvbSBkaXYgcGFyYSBtb3N0cmFyIGxlZ2VuZGEgc2VwYXJhZGENCmR5Z3JhcGgoc2hfeHRzKSAlPiUNCiAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0Q2lyY2xlU2l6ZSA9IDUsIA0KICAgICAgICAgICAgICBoaWdobGlnaHRTZXJpZXNCYWNrZ3JvdW5kQWxwaGEgPSAwLjIsDQogICAgICAgICAgICAgIGhpZ2hsaWdodFNlcmllc09wdHMgPSBsaXN0KHN0cm9rZVdpZHRoID0gMyksDQogICAgICAgICAgICAgIGhpZGVPbk1vdXNlT3V0ID0gRkFMU0UpICU+JQ0KICBkeUxlZ2VuZChzaG93ID0gIm9ubW91c2VvdmVyIiwgbGFiZWxzRGl2PSJsYWJlbHMiLCBsYWJlbHNTZXBhcmF0ZUxpbmVzID0gVFJVRSkNCg0KIyB0ZW50YW5kbyBtb3N0cmFyIHPDsyB1bWEgbGVnZW5kYSBwb3IgdmV6DQoNCiMjIHVodSwgZnVuY2lvbm91IQ0KIyMgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzU5NDM1ODMvcGxhaW4tZHlncmFwaHMtamF2YXNjcmlwdC1vcHRpb25zLWluLXItc2hpbnkNCg0KZHlncmFwaChzaF94dHMpICU+JQ0KICBkeUhpZ2hsaWdodChoaWdobGlnaHRDaXJjbGVTaXplID0gNSwgDQogICAgICAgICAgICAgIGhpZ2hsaWdodFNlcmllc0JhY2tncm91bmRBbHBoYSA9IDAuMiwNCiAgICAgICAgICAgICAgaGlnaGxpZ2h0U2VyaWVzT3B0cyA9IGxpc3Qoc3Ryb2tlV2lkdGggPSAzKSwNCiAgICAgICAgICAgICAgaGlkZU9uTW91c2VPdXQgPSBGQUxTRSkgJT4lDQogIGR5TGVnZW5kKHNob3cgPSAiYWx3YXlzIikgJT4lDQogIGR5Q1NTKHRleHRDb25uZWN0aW9uKCINCiAgICAgLmR5Z3JhcGgtbGVnZW5kID4gc3BhbiB7IGRpc3BsYXk6IG5vbmU7IH0NCiAgICAgLmR5Z3JhcGgtbGVnZW5kID4gc3Bhbi5oaWdobGlnaHQgeyBkaXNwbGF5OiBpbmxpbmU7IH0NCiAgIikpDQoNCmBgYA0KPGRpdiBpZD0ibGFiZWxzIj4NCjwvZGl2Pg0KDQojIE8gYmFsYW7Dp28gcGF0cmltb25pYWwNCg0KIyMgT3MgYXRpdm9zDQoNCmBgYHtyfQ0KbGlicmFyeShwbG90bHkpDQoNCiMgbGUgb3MgZGFkb3MNCg0KYXRpdm8gPC0gcmVhZC5jc3YyKCJsaW5rcy1hdGl2by5jc3YiKQ0KYXRpdm8kdmFsb3IgPC0gYXMubnVtZXJpYyhnc3ViKCJbLl0iLCAiIiwgYXRpdm8kdmFsb3IpKQ0KDQpwYXNzaXZvIDwtIHJlYWQuY3N2MigibGlua3MtcGFzc2l2by5jc3YiKQ0KcGFzc2l2byR2YWxvciA8LSBhcy5udW1lcmljKGdzdWIoIlsuXSIsICIiLCBwYXNzaXZvJHZhbG9yKSkNCg0KIyBjb3Jlcw0KDQptdHhfdHJlc19jb3JlcyA8LSBjb2wycmdiKHRyZXNfY29yZXNfcGFzdGVpcykNCg0KY29yZXMgPC0gTlVMTA0KZm9yIChpIGluIDE6ZGltKG10eF90cmVzX2NvcmVzKVsyXSApIHsNCiAgY29yZXMgPC0gYyhjb3JlcywgcGFzdGUoInJnYmEoIiwgbXR4X3RyZXNfY29yZXNbMSxpXSwiLCAiLCAgbXR4X3RyZXNfY29yZXNbMixpXSwiLCAiLCAgbXR4X3RyZXNfY29yZXNbMyxpXSwiLCAwLjcpIiwgc2VwID0gIiIpKQ0KfQ0KDQp0YmxfY29yZXMgPC0gZGF0YS5mcmFtZSgiZW50ZSIgPSBsZXZlbHMoYXRpdm8kZW50ZSksY29yZXMpDQoNCiMgZnVuY2FvIGRlIHBsb3RhZ2VtDQoNCnBsb3RhX3NhbmtleSA8LSBmdW5jdGlvbihkYWRvcywgcm90dWxvcywgY29yX25vcyl7DQogIHBsb3RfbHkoDQogICAgdHlwZSA9ICJzYW5rZXkiLA0KICAgIG9yaWVudGF0aW9uID0gImgiLA0KICAgIG9wYWNpdHkgPSAwLjYsDQogICAgd2lkdGggPSA4MDAsDQogICAgaGVpZ2h0ID0gNjAwLA0KICAgIHRleHRmb250ID0gbGlzdCgNCiAgICAgIGZhbWlseSA9ICJTb3VyY2UgU2FucyBQcm8iLA0KICAgICAgY29sb3IgPSAiIzQ0NDQ0NCIsDQogICAgICBzaXplID0gMTIpLA0KICAgIA0KICAgIG5vZGUgPSBsaXN0KA0KICAgICAgbGFiZWwgPSByb3R1bG9zLA0KICAgICAgY29sb3IgPSBjb3Jfbm9zLCAjIzAwNGE5Mw0KICAgICAgcGFkID0gMTAsDQogICAgICB0aGlja25lc3MgPSAyNSwNCiAgICAgIGxpbmUgPSBsaXN0KA0KICAgICAgICBjb2xvciA9IGNvcl9ub3MsDQogICAgICAgIHdpZHRoID0gMCkpLA0KICAgIA0KICAgIGhvdmVybGFiZWwgPSBsaXN0KA0KICAgICAgZm9udCA9IGxpc3QoDQogICAgICAgIGZhbWlseSA9ICJTb3VyY2UgU2FucyBQcm8iKSksDQogICAgDQogICAgbGluayA9IGxpc3QoDQogICAgICBzb3VyY2UgPSBkYWRvcyRzcmMsDQogICAgICB0YXJnZXQgPSBkYWRvcyR0cmcsDQogICAgICB2YWx1ZSA9ICBkYWRvcyR2YWxvciwNCiAgICAgIGNvbG9yID0gIGRhZG9zJGNvcmVzKSkgJT4lIA0KICANCiAgICBsYXlvdXQoDQogICAgICB0aXRsZSA9ICIiLA0KICAgICAgZm9udCA9IGxpc3QoDQogICAgICAgIGZhbWlseSA9ICJTb3VyY2UgU2FucyBQcm8iLA0KICAgICAgICBzaXplID0gMTEsDQogICAgICAgIGNvbG9yID0gIiMwMDRhOTMiKSkNCn0NCg0KIyBmdW5jYW8gcGFyYSBwcm9jZXNzYXIgb3MgZGFkb3MgZSBjaGFtYXIgYSBmdW7Dp8OjbyBkZSBwbG90YWdlbQ0KDQojIyMjIyBpbmNsdWlyIGFyZ3VtZW50byBuYSBmdW7Dp8OjbyBwYXJhIGNvciBkb3MgbsOzcyENCg0KcGxvdGFfZW50ZSA8LSBmdW5jdGlvbihlbnRlX2luLCBkYWRvcywgY29yX25vcyl7DQogIA0KICBpZiAoZW50ZV9pbiA9PSAiQ29uc29saWRhZG8iKSB7DQogICAgZGFkb3NfZW50ZSA8LSBkYWRvc30NCiAgICBlbHNlIHtkYWRvX2VudGUgPC0gZGFkb3MgJT4lIGZpbHRlcihlbnRlID09IGVudGVfaW4pDQogIH0NCiAgDQogIGxpc3RhX25vcyA8LSB1bmlxdWUoYyhsZXZlbHMoZGFkb3NfZW50ZSR1cCksIGxldmVscyhkYWRvc19lbnRlJGRvd24pKSkNCiAgbnVtZXJvc19ub3MgPC0gMDoobGVuZ3RoKGxpc3RhX25vcyktMSkNCiAgbm9zIDwtIGRhdGEuZnJhbWUobGlzdGFfbm9zLCBudW1lcm9zX25vcykNCiAgDQogIG1hdHJpeiA8LSBkYWRvc19lbnRlICU+JQ0KICAgIGxlZnRfam9pbihub3MsIGJ5ID0gYygidXAiID0gImxpc3RhX25vcyIpKSAlPiUNCiAgICByZW5hbWUoc3JjID0gbnVtZXJvc19ub3MpICU+JQ0KICAgIGxlZnRfam9pbihub3MsIGJ5ID0gYygiZG93biIgPSAibGlzdGFfbm9zIikpICU+JQ0KICAgIHJlbmFtZSh0cmcgPSBudW1lcm9zX25vcykNCiAgDQogIG1hdHJpeiA8LSBtYXRyaXogJT4lDQogICAgbGVmdF9qb2luKHRibF9jb3JlcykNCiAgDQogIHBsb3RhX3NhbmtleShtYXRyaXosIGxpc3RhX25vcywgY29yX25vcykNCiAgI3JldHVybihtYXRyaXopDQp9DQoNCiNkYWRvc19jb25zb2xpZGFkbyA8LSBnZXJhX2RhZG9zX2VudGUoIkNvbnNvbGlkYWRvIikNCiNkYWRvc19VbmlhbyA8LSBnZXJhX2RhZG9zX2VudGUoIlVuacOjbyIpDQojZGFkb3NfRXN0YWRvcyA8LSBnZXJhX2RhZG9zX2VudGUoIkVzdGFkb3MiKQ0KI2RhZG9zX011bmljaXBpb3MgPC0gZ2VyYV9kYWRvc19lbnRlKCJNdW5pY8OtcGlvcyIpDQoNCnBsb3RhX2VudGUoIkNvbnNvbGlkYWRvIiwgYXRpdm8sICIjMTcwZGNlIikNCnBsb3RhX2VudGUoIkNvbnNvbGlkYWRvIiwgcGFzc2l2bywgIiNjZTBlMGUiKQ0KDQoNCmBgYA0KIyMgRGlhZ3JhbWEgQ29uc29saWRhZG8NCg0KYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojcGxvdGFfZW50ZSgiQ29uc29saWRhZG8iKQ0KYGBgDQoNCg==